﻿
//===============================================================================
//
//  IMPORTANT NOTICE, PLEASE READ CAREFULLY:
//
//  => This code is licensed under the GNU General Public License (GPL v3). A copy of the license is available at:
//        https://www.gnu.org/licenses/gpl.txt
//
//  => As stated in the license text linked above, "The GNU General Public License does not permit incorporating your program into proprietary programs". It also does not permit incorporating this code into non-GPL-licensed code (such as MIT-licensed code) in such a way that results in a non-GPL-licensed work (please refer to the license text for the precise terms).
//
//  => Licenses that permit proprietary use are available at:
//        http://www.cshtml5.com
//
//  => Copyright 2019 Userware/CSHTML5. This code is part of the CSHTML5 product (cshtml5.com).
//
//===============================================================================



namespace System.Xml.Serialization
{
    using System;
    using System.Xml.Schema;

    /// <summary>
    /// Indicates that a public field or property represents an XML element when
    /// the System.Xml.Serialization.XmlSerializer serializes or deserializes the
    /// object that contains it.
    /// </summary>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)]
    public partial class XmlElementAttribute : System.Attribute
    {
        string elementName;
        Type type;
        string ns;
        string dataType;
        bool nullable;
        bool nullableSpecified;
        XmlSchemaForm form = XmlSchemaForm.None;
        int order = -1;

        /// <summary>
        /// Initializes a new instance of the System.Xml.Serialization.XmlElementAttribute
        /// class.
        /// </summary>
        public XmlElementAttribute()
        {
        }

        /// <summary>
        /// Initializes a new instance of the System.Xml.Serialization.XmlElementAttribute
        /// class and specifies the name of the XML element.
        /// </summary>
        /// <param name="elementName">The XML element name of the serialized member.</param>
        public XmlElementAttribute(string elementName)
        {
            this.elementName = elementName;
        }

        /// <summary>
        /// Initializes a new instance of the System.Xml.Serialization.XmlElementAttribute
        /// class and specifies a type for the member to which the System.Xml.Serialization.XmlElementAttribute
        /// is applied. This type is used by the System.Xml.Serialization.XmlSerializer
        /// when serializing or deserializing object that contains it.
        /// </summary>
        /// <param name="type">The System.Type of an object derived from the member's type.</param>
        public XmlElementAttribute(Type type)
        {
            this.type = type;
        }

        /// <summary>
        /// Initializes a new instance of the System.Xml.Serialization.XmlElementAttribute
        /// and specifies the name of the XML element and a derived type for the member
        /// to which the System.Xml.Serialization.XmlElementAttribute is applied. This
        /// member type is used when the System.Xml.Serialization.XmlSerializer serializes
        /// the object that contains it.
        /// </summary>
        /// <param name="elementName">The XML element name of the serialized member.</param>
        /// <param name="type">The System.Type of an object derived from the member's type.</param>
        public XmlElementAttribute(string elementName, Type type)
        {
            this.elementName = elementName;
            this.type = type;
        }

        /// <summary>
        /// Gets or sets the object type used to represent the XML element.
        /// </summary>
        public Type Type
        {
            get { return type; }
            set { type = value; }
        }

        /// <summary>
        /// Gets or sets the name of the generated XML element.
        /// </summary>
        public string ElementName
        {
            get { return elementName == null ? string.Empty : elementName; }
            set { elementName = value; }
        }

        /// <summary>
        /// Gets or sets the namespace assigned to the XML element that results when
        /// the class is serialized.
        /// </summary>
        public string Namespace
        {
            get { return ns; }
            set { ns = value; }
        }

        // Exceptions:
        //   System.Exception:
        //     The XML Schema data type you have specified cannot be mapped to the.NET data
        //     type.
        /// <summary>
        /// Gets or sets the XML Schema definition (XSD) data type of the XML element
        /// generated by the System.Xml.Serialization.XmlSerializer.
        /// </summary>
        public string DataType
        {
            get { return dataType == null ? string.Empty : dataType; }
            set { dataType = value; }
        }

        /// <summary>
        /// Gets or sets a value that indicates whether the System.Xml.Serialization.XmlSerializer
        /// must serialize a member that is set to null as an empty tag with the xsi:nil
        /// attribute set to true.
        /// </summary>
        public bool IsNullable
        {
            get { return nullable; }
            set
            {
                nullable = value;
                nullableSpecified = true;
            }
        }

        internal bool IsNullableSpecified
        {
            get { return nullableSpecified; }
        }

        /// <summary>
        /// Gets or sets a value that indicates whether the element is qualified.
        /// </summary>
        public XmlSchemaForm Form
        {
            get { return form; }
            set { form = value; }
        }

        /// <summary>
        /// Gets or sets the explicit order in which the elements are serialized or deserialized.
        /// </summary>
        public int Order
        {
            get { return order; }
            set
            {
                if (value < 0)
                    throw new ArgumentException("Order cannot be negative.");
                order = value;
            }
        }
    }
}